home *** CD-ROM | disk | FTP | other *** search
/ Complete Internet Archive / Complete Internet Archive.iso / Web Forms / mailto.pl.txt < prev    next >
Encoding:
Text File  |  1997-01-26  |  12.9 KB  |  380 lines

  1.  
  2.  
  3. #!/usr/bin/perl
  4.  
  5. ############################################################
  6. #              mailto.cgi
  7. #                 v1.2.5
  8. #                Meng Weng Wong
  9. #         Thu Feb 22 02:47:49 EST 1996
  10. # $Id: mailto.cgi,v 1.6 1996/05/18 07:10:56 mengwong Exp mengwong $
  11. # accepts a form submission and mails all fields to an address
  12. # specified within the form.
  13. # requires perl 5, available ftp.netlabs.com
  14. # PLEASE READ THE DOCUMENTATION
  15. #    http://icg.resnet.upenn.edu/mailto.html
  16. # TO DO (planned upgrades)
  17. # I have another problem you might be able to help with. My purpose in
  18. # setting up the form is to allow clients of my service bureau to fill out an
  19. # order form, and then attach a file to the resulting email form. If
  20. # possible, it would be nice if they could click an "Attach" button, get the
  21. # usual Mac or Windows file dialog, pick a file, and return to the form, then
  22. # when they click the "Submit" I would receive a form like your mailto.cgi
  23. # script makes, with the chosen file attached.
  24. # Alternatively, after the mailto script sends the form to me, the following
  25. # html page would provide an opportunity to send another message with file
  26. # attached, or to send the file via ftp.
  27. ############################################################
  28.  
  29. # ----------------------------------------------------------
  30. #                initialization
  31. # ----------------------------------------------------------
  32.  
  33. # if you've downloaded mailto.cgi for use as a local installation,
  34. # you MUST change all the following information.
  35.  
  36. # who's in charge of this installation of webmail?
  37. $maintainer = 'mengwong@pobox.com';
  38.  
  39. # what's my local Fully Qualified Domain Name?
  40. $hostname   = "icg.resnet.upenn.edu";
  41.  
  42. # all webmails sent will be BCC'ed to this address
  43. # (typically the maintainer).  comment out if you don't want
  44. # such BCCs to be sent.
  45. $autobcc = 'mengwong+webmail@pobox.com';
  46.  
  47. # where's sendmail located?
  48. $mail = "/usr/lib/sendmail";
  49.  
  50. # who's the default From if none is given?  this address
  51. # is supposed to bounce.
  52. $default_from = 'sender.did.not.provide.an.email.address@webmail.gateway (WebMail gateway, no From given)';
  53.  
  54. # String to prepend to subject of every e-mail message
  55. $subj_prefix = "WebMail: ";
  56.  
  57. # submissions that don't specify host in the "to" portion
  58. # end up with this default one.
  59. $home_host = "mengwong.com";
  60.  
  61. $disclaimer = "
  62.  # --------------------------------------------------------------
  63.  # This message comes to you via a Web-to-Email gateway.
  64.  # The person who originated this message may not be provably
  65.  # identifiable.  The webmail gateway takes no responsibility
  66.  # for this message; it even encourages a healthy skepticism on
  67.  # your part.  Our best guess at the identity of the originator,
  68.  # which may or may not reassure you, is:
  69.  #   real_remote_address
  70.  # This experimental gateway is maintained as a public
  71.  # service.  Please report any abuses to the maintainer,
  72.  # $maintainer, who otherwise has and wants
  73.  # nothing to do with this message whatsoever.
  74.  # You can get more information about the gateway at
  75.  #   http://icg.resnet.upenn.edu/mailto.html
  76.  # --------------------------------------------------------------
  77. ";
  78.  
  79. # the bottom line on the "yes, your mail was sent" page
  80. $credit = "submitted via <A HREF=\"http://icg.resnet.upenn.edu/mailto.html\">mailto.cgi</A>, a public service utility written by <A HREF=\"http://pobox.com/~mengwong/\">Meng Weng Wong</A>";
  81.  
  82. # what hosts are to be forbidden from posting to mailto.cgi?
  83. @disallowed_regexps = ("saturn.caps.maine.edu", "www.iao.com");
  84.  
  85. # ----------------------------------------------------------
  86. # no user-serviceable parts below this line
  87. # ----------------------------------------------------------
  88.  
  89. $webmailversion = "v1.2.2";
  90.  
  91. $ENV{"PATH"} = "";
  92. $ENV{'IFS'} = '';
  93.  
  94. @specialnames = ("to", "cc", "from", "body", "subject",
  95.          "continue_url", "continue_text",
  96.          "leading_spaces", "separator",
  97.          "required_fields", "sort_order",
  98.          "body_bgcolor", "body_background",
  99.          "body_link", "body_vlink", "body_text",
  100.          "first_line", "mailto_comment");
  101.  
  102. if (grep ($ENV{REMOTE_HOST} =~ /$_/, @disallowed_regexps)) {
  103.     print "Content-type: text/html\n\nYou are not permitted to use this page.  Sorry.\n";
  104.     exit;
  105. }
  106.  
  107. # Tell WWW that we're an HTML document
  108. &ReadParse;
  109.  
  110. if (! keys %in) {
  111.     print "Location: http://icg.resnet.upenn.edu/mailto.html\n\nPlease check out <A HREF=\"http://icg.resnet.upenn.edu/mailto.html\">http://icg.resnet.upenn.edu/mailto.html</A>\n";
  112. }
  113.  
  114. print "Content-type: text/html\n\n";
  115.  
  116. $remote_host = $ENV{"REMOTE_HOST"};
  117. $remote_host = "unknown" if ($remote_host =~ /^\s*$/);
  118. $remote_user = $ENV{"REMOTE_IDENT"};
  119. $remote_user = "unknown" if ($remote_user =~ /^\s*$/);
  120. $real_remote_address = substr("$remote_user\@$remote_host", 0, 200);
  121. $disclaimer =~ s/real_remote_address/$real_remote_address/;
  122.  
  123. # ----------------------------------------------------------
  124. #             build the <BODY> tag
  125. # ----------------------------------------------------------
  126.  
  127. @bodyattributes = grep(/^body_/ && $in{$_} =~ /\S/, @specialnames);
  128. if (@bodyattributes) {
  129.     $bodytag = "<BODY";
  130.     for (@bodyattributes) {
  131.     $tentativetag = $in{$_};
  132.     if ($_ =~ /bgcolor|link|vlink|text/ && $tentativetag =~ /^[0-9a-f]{6}$/i) {
  133.         $tentativetag = "#$tentativetag";
  134.     }
  135.     ($attributename = uc($_)) =~ s/^BODY_//;
  136.     $bodytag .= " $attributename=\"$tentativetag\"";
  137.     }
  138.     $bodytag .= ">";
  139. }
  140.  
  141. # ----------------------------------------------------------
  142. #      make sure all required fields are present
  143. # ----------------------------------------------------------
  144.  
  145. @required_fields = ("to", split(/\s*,\s*|\000/, $in{'required_fields'}));
  146. @missing_fields = grep ($in{$_} !~ /\S/, @required_fields);
  147. if (@missing_fields) {
  148.     $errormessage = "You did not provide sufficient information.\nYou are required to fill out the following:\n\n<UL>";
  149.     $errormessage .= join("\n<LI> ", "", @missing_fields);
  150.     $errormessage .= "\n</UL>\n\nPlease go back and fill out the form again.\n";
  151.     &Exit("Insufficient Information", $errormessage);
  152. }
  153.  
  154. # ----------------------------------------------------------
  155. #                build the To:
  156. # ----------------------------------------------------------
  157.  
  158. # Untaint so we don't get nasty shell metacharacters.
  159. $to = $in{"to"};
  160. $to_orig = $to;
  161. $to =~ /^([\w, \.\%\!\@-]*)$/;  $to = $1; # Untaint it
  162. $to =~ s/^\s+//; s/\s+$//;
  163. &Exit("Illegal characters found in \"To\" address.") if ($to ne $to_orig);
  164.  
  165. $to = "$to\@$home_host" if ($to !~ /\@\S+/);
  166.  
  167. # ----------------------------------------------------------
  168. #             same for cc
  169. # ----------------------------------------------------------
  170.  
  171. $cc = $in{"cc"};
  172. $cc_orig = $cc;
  173. $cc =~ /^([\w, \.\%\!\@-]*)$/;  $cc = $1; # Untaint it
  174. undef $cc if ($cc ne $cc_orig);
  175. undef $cc if ($cc !~ /\@\S+$/);
  176.  
  177. if (defined($cc)) {
  178.     $ccline = "CC: $cc\n";
  179.     $cclinehtml = "<EM>CC:</EM> $cc<BR>\n";
  180. }
  181.  
  182. # ----------------------------------------------------------
  183. #            and for mailto_comment
  184. # ----------------------------------------------------------
  185.  
  186. if ($in{"mailto_comment"} =~ /\S/) {
  187.     $mailtocomment = $in{'mailto_comment'};
  188.     $mailtocommenthtml = "<EM>X-Mailto-Comment:</EM> $mailtocomment<BR>\n";
  189.     $mailtocomment = "X-Mailto-Comment: $in{'mailto_comment'}\n";
  190. }
  191.  
  192. # ----------------------------------------------------------
  193. #            and for first_line
  194. # ----------------------------------------------------------
  195.  
  196. if ($in{"first_line"} =~ /\S/) {
  197.     $firstline = $in{'first_line'} . "\n\n";
  198. }
  199.  
  200. # ----------------------------------------------------------
  201. #               make up the from
  202. # ----------------------------------------------------------
  203.  
  204. $from = $in{"from"};
  205. if ($in{'from'} eq "") { $from = $default_from; }
  206. elsif ($from !~ /\@/)  { $from = "$real_remote_address ($from)"; }
  207. elsif (defined($in{'name'})) { $in{'name'} = substr($in{'name'}, 0, 200);
  208.                    $from .= " ($in{'name'})"; }
  209.  
  210. # ----------------------------------------------------------
  211. #        do we get to mention an http_referer?
  212. # ----------------------------------------------------------
  213.  
  214. if (defined $ENV{'HTTP_REFERER'}) {
  215.     $http_referer = "X-HTTP-Referer: $ENV{'HTTP_REFERER'}\n";
  216. }
  217.  
  218. # ----------------------------------------------------------
  219. #             get the body working
  220. # ----------------------------------------------------------
  221.  
  222. $body = $in{"body"};
  223.  
  224. # ----------------------------------------------------------
  225. #              build the subject
  226. # ----------------------------------------------------------
  227.  
  228. $subject = $in{"subject"};
  229. $subject = $subj_prefix . $subject;
  230.  
  231. # ----------------------------------------------------------
  232. #       do key/value pairs want leading spaces?
  233. #         and how do we separate them?
  234. #           and how do we sort them?
  235. # ----------------------------------------------------------
  236.  
  237. $leading_spaces = $in{"leading_spaces"};
  238. $leadingspaces = "    " if (! defined ($leading_spaces) ||
  239.                 $leading_spaces =~ /^(1|yes|true|y|t|do|want)$/i);
  240.  
  241. $separator = $in{'separator'};
  242. $separator = " = " unless (defined ($separator));
  243.    if ($separator =~ /colon/)  { $separator = ": "; }
  244. elsif ($separator =~ /dash/)   { $separator = " - "; }
  245. elsif ($separator =~ /hyphen/) { $separator = " -- "; }
  246. elsif ($separator =~ /line/)   { $separator = " --- "; }
  247. elsif ($separator =~ /equal/)  { $separator = " = "; }
  248. elsif ($separator =~ /space/)  { $separator = " "; }
  249. elsif ($separator =~ /tab/)    { $separator = "\t"; }
  250.  
  251. $sort_order = $in{'sort_order'};
  252. if (defined ($sort_order)) {
  253.     $sortorder = sub {$a cmp $b}            if ($sort_order =~ /alphabetical/i);
  254.     $sortorder = sub {lc($a) cmp lc($b)}    if ($sort_order =~ /alphabetical, case insensitive/i);
  255.     $sortorder = sub {$b cmp $a}            if ($sort_order =~ /reverse alphabetical/i);
  256.     $sortorder = sub {lc($b) cmp lc($a)}    if ($sort_order =~ /reverse alphabetical, case insensitive/i);
  257.     undef ($sortorder)                      if ($sort_order =~ /undefined|none|as.?is/i);
  258. }
  259.  
  260. # sorted_in_keys is predefined in ReadParse, thus sort_order=none by default
  261.  
  262. if (defined ($sortorder)) {
  263.     @sorted_in_keys = sort { &$sortorder($a, $b) } keys %in;
  264. }
  265.  
  266. foreach $key (@sorted_in_keys) {
  267.     next if (grep($key eq $_, @specialnames));
  268.     $pad = " " x length("$leadingspaces$key$separator");
  269.     $in{$key} =~ s/[\000\n]/\n$pad/g;
  270.     $instuff .= "$leadingspaces$key$separator$in{$key}\n";
  271. }
  272.  
  273. # ----------------------------------------------------------
  274. #           now we're ready to send the mail
  275. # ----------------------------------------------------------
  276.  
  277. if (($autobcc eq "mengwong+webmail\@pobox.com") && ($hostname eq "icg.resnet.upenn.edu")) { $realautobcc = $autobcc; }
  278.                                              else { $realautobcc = ""; }
  279.  
  280. # print STDERR "opening \"|$mail $to $cc $realautobcc\"\n";
  281. open(MAIL,"|$mail $to $cc $realautobcc") ||  &Exit("Could not execute \"$mail\"");
  282.  
  283. print MAIL <<"TAG";
  284. X-Mailer: Meng's mailto.cgi $webmailversion at $hostname
  285. From: $from
  286. X-Ident-From: $real_remote_address
  287. Subject: $subject
  288. To: $to
  289. Precedence: bulk
  290. $ccline$http_referer$mailtocomment
  291. $firstline$instuff
  292. $body
  293.  
  294. $disclaimer
  295. TAG
  296.  
  297. close(MAIL);
  298.  
  299. if (defined($in{'continue_text'}) &&
  300.     defined($in{'continue_url'})) {
  301.     $continue = "<A HREF=\"$in{'continue_url'}\">$in{'continue_text'}</A>";
  302. }
  303.  
  304. # If we are here, then success -- print a happy message
  305. $toprinttostdout = <<TAG;
  306. <TITLE>Submission Receipt</TITLE>
  307. $bodytag
  308. <H1>Your message has been sent!</H1>
  309. $continue
  310. <HR>
  311. <EM>To:</EM> $to<BR>
  312. $mailtocommenthtml$cclinehtml<EM>From:</EM> $from<BR>
  313. <EM>Subject:</EM> $subject<BR>
  314. <EM>Submitted by:</EM> $real_remote_address<P>
  315.  
  316. <PRE>$firstline$instuff
  317. $body</PRE>
  318. <HR>
  319. $credit
  320. TAG
  321.  
  322. print $toprinttostdout;
  323.  
  324. # ----------------------------------------------------------
  325. #              functions
  326. # ----------------------------------------------------------
  327.  
  328. # Exit the script displaying the appropriate error message. (format 2)
  329. sub Exit {
  330.     local($errorheader) = shift(@_);
  331.  
  332.     print "<TITLE>Webmail: $errorheader</TITLE>\n";
  333.     print $bodytag;
  334.     print "<H1>$errorheader</H1>\n";
  335.     print @_;
  336.     print "<P><HR>Unable to send the message.\n";
  337.  
  338.     exit(2);
  339. }
  340.  
  341. sub ReadParse {
  342.     local (*in) = @_ if @_;
  343.  
  344.     local ($i, $key, $val);
  345.  
  346.     # Read in text
  347.     if    ($ENV{'REQUEST_METHOD'} eq "GET") { $in = $ENV{'QUERY_STRING'}; }
  348.     elsif ($ENV{'REQUEST_METHOD'} eq "POST") { read(STDIN,$in,$ENV{'CONTENT_LENGTH'}); }
  349.  
  350.     @in = split(/&/,$in);
  351.  
  352.     foreach $i (0 .. $#in) {
  353.     # Convert plus's to spaces
  354.     $in[$i] =~ s/\+/ /g;
  355.  
  356.     # Split into key and value.  
  357.     ($key, $val) = split(/=/,$in[$i],2); # splits on the first =.
  358.  
  359.     # Convert %XX from hex numbers to alphanumeric
  360.     $key =~ s/%(..)/pack("c",hex($1))/ge;
  361.     $val =~ s/%(..)/pack("c",hex($1))/ge;
  362.  
  363.     push (@sorted_in_keys, $key) unless defined($in{$key});
  364.  
  365.     # Associate key and value
  366.     $in{$key} .= "\000" if (defined($in{$key})); # \0 is the multiple separator
  367.     $in{$key} .= $val;
  368.     }
  369.  
  370.     return 1; # just for fun
  371. }
  372.  
  373.